package okhttp3Demo;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

import okhttp3Demo.interceptor.ProgressRequestBody;
import okhttp3Demo.interceptor.ProgressRequestListener;
import okhttp3Demo.interceptor.TimeoutRetryInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Created by lining on 2018/05/03.
 */
public class OkHttpClientFactory {
    private static final byte[] LOCKER = new byte[0];
    private static Map<String, OkHttpClient> okHttpClientMap = new HashMap<>();
    private static OkHttpClientFactory mInstance;
    private static Logger logger = LoggerFactory.getLogger(OkHttpClientFactory.class);

    public static final String DEFAULT_CLIENT = "default";
    public static final String DEFAULT_QUERY_CLIENT = "default_query";
    public static final String ASSET_SYNC_CLIENT = "assetSyncClient";
    public static final String FABAOAPI_ENCLOSURE_CLIENT = "fabaoEnclosure";
    public static final String SMART_CALL_CLIENT = "smartCallClient";
    public static final String EMI_CALL_CLIENT = "emiCallClient";
    public static final String BIZ_QUERY_DEADLINE_ASSET_CLIENT = "biz_query_deadline_asset_retry_query";
    public static final String BAI_DU_NEWS = "bai_du_news";
    public static final String SZZJ_DATA = "szzj_data";

    private OkHttpClientFactory() {
        okHttpClientMap.put(DEFAULT_CLIENT, produceClient(2L, 10L, 10L, 10));//默认
        okHttpClientMap.put(DEFAULT_QUERY_CLIENT, produceClient(2L, 3L, 3L, 10));//默认
        okHttpClientMap.put(ASSET_SYNC_CLIENT, produceClient(2L, 3L, 3L, 10));//默认
        okHttpClientMap.put(SMART_CALL_CLIENT, produceClient(2L, 3L, 60L, 10));//默认
        okHttpClientMap.put(EMI_CALL_CLIENT, produceSSLClient(5L, 3L, 30L, 10));//默认

        List<Interceptor> interceptors = new ArrayList<>();
        interceptors.add(new TimeoutRetryInterceptor(3,5000));
        okHttpClientMap.put(BIZ_QUERY_DEADLINE_ASSET_CLIENT, produceClient(2L, 5L, 20L, 10,interceptors));//默认
        okHttpClientMap.put(BAI_DU_NEWS, produceClient(15L, 10L, 60L, 10,interceptors));//默认
        okHttpClientMap.put(SZZJ_DATA, produceClient(15L, 10L, 60L, 10,interceptors));//默认

        interceptors = new ArrayList<>();
        interceptors.add(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request original = chain.request();

                Request request = original.newBuilder()
                        .method(original.method(), new ProgressRequestBody(original.body(), new ProgressRequestListener() {
                            @Override
                            public void onRequestProgress(long bytesWrite, long contentLength, boolean done) {
                                if (done) logger.info("上传完成,总共:{}字节", contentLength);
                                else {
                                    if (contentLength > 0) {
                                        long progress = bytesWrite * 100 / contentLength;
                                        if (progress % 20 == 0)
                                            logger.info("上传:{}%,上传:{}字节,总共:{}字节", progress, bytesWrite, contentLength);
                                    }
                                }
                            }
                        }))
                        .build();
                return chain.proceed(request);
            }
        });

        okHttpClientMap.put(FABAOAPI_ENCLOSURE_CLIENT, produceClient(2L, 30L, 60L, 5,interceptors));//法宝上传附件接口
    }


    public static OkHttpClientFactory getInstance() {
        if (mInstance == null) {
            synchronized (LOCKER) {
                if (mInstance == null) {
                    mInstance = new OkHttpClientFactory();
                }
            }
        }
        return mInstance;
    }

    public OkHttpClient getDefaultClient() {
        return okHttpClientMap.get(DEFAULT_CLIENT);
    }

    public OkHttpClient getClient(String name) {
        return okHttpClientMap.get(name);
    }

    /**
     * 创建忽略认证的客户端
     * @param connectTime
     * @param writeTime
     * @param readTime
     * @param maxRequestsPerHost
     * @return
     */
    public OkHttpClient produceSSLClient(Long connectTime, Long writeTime, Long readTime, Integer maxRequestsPerHost){
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if(connectTime != null && connectTime.intValue() > 0)builder.connectTimeout(connectTime, TimeUnit.SECONDS);//连接超时
        if(writeTime != null && writeTime.intValue() > 0)builder.writeTimeout(writeTime, TimeUnit.SECONDS);//连接超时
        if(readTime != null && readTime.intValue() > 0)builder.readTimeout(readTime, TimeUnit.SECONDS);//连接超时
        builder.hostnameVerifier(SSLSocketClient.getHostnameVerifier());
        builder.sslSocketFactory(SSLSocketClient.getSSLSocketFactory());

        OkHttpClient client = builder.build();
        if(maxRequestsPerHost != null && maxRequestsPerHost > 0)client.dispatcher().setMaxRequestsPerHost(maxRequestsPerHost);
        return client;
    }


    public OkHttpClient produceClient(Long connectTime, Long writeTime, Long readTime, Integer maxRequestsPerHost){
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if(connectTime != null && connectTime.intValue() > 0)builder.connectTimeout(connectTime, TimeUnit.SECONDS);//连接超时
        if(writeTime != null && writeTime.intValue() > 0)builder.writeTimeout(writeTime, TimeUnit.SECONDS);//连接超时
        if(readTime != null && readTime.intValue() > 0)builder.readTimeout(readTime, TimeUnit.SECONDS);//连接超时
        OkHttpClient client = builder.build();
        if(maxRequestsPerHost != null && maxRequestsPerHost > 0)client.dispatcher().setMaxRequestsPerHost(maxRequestsPerHost);
        return client;
    }

    public OkHttpClient produceClient(Long connectTime,Long writeTime,Long readTime,Integer maxRequestsPerHost,List<Interceptor> interceptors){
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if(connectTime != null && connectTime.intValue() > 0)builder.connectTimeout(connectTime, TimeUnit.SECONDS);//连接超时
        if(writeTime != null && writeTime.intValue() > 0)builder.writeTimeout(writeTime, TimeUnit.SECONDS);//连接超时
        if(readTime != null && readTime.intValue() > 0)builder.readTimeout(readTime, TimeUnit.SECONDS);//连接超时
        if(interceptors != null && !interceptors.isEmpty()){
            for (Interceptor interceptor : interceptors) {
                builder.addInterceptor(interceptor);
            }
        }
        OkHttpClient client = builder.build();
        if(maxRequestsPerHost != null && maxRequestsPerHost > 0)client.dispatcher().setMaxRequestsPerHost(maxRequestsPerHost);
        return client;
    }
}